package form

import (
	"errors"
	"github.com/gin-gonic/gin"
	"path/filepath"
	"strconv"
	"time"
	"yak.admin/src/entity"
	"yak.admin/src/module/api/user/repository"
	"yak.admin/src/service"
	"yak.admin/src/util"
)

type NicknameForm struct {
	Nickname string `form:"nickname" validate:"required,min=2,max=32" chn:"昵称"`
}

type UsernameForm struct {
	Username     string `form:"username" validate:"required,max=128" chn:"用户名"`
}

type SexForm struct {
	Sex     int `form:"sex" chn:"性别"`
}

type AgeForm struct {
	Age     int `form:"age" chn:"年龄"`
}

type CompanyForm struct {
	Company  string `form:"company" validate:"required,max=128" chn:"单位名称"`
}

type JobForm struct {
	Job      string `form:"job" validate:"required,max=128" chn:"担任职务"`
}

type JobRankForm struct {
	JobRank     string `form:"job_rank" validate:"required,max=128" chn:"职级"`
}

type AddressFrom struct {
	Province string `form:"province" validate:"required" chn:"省"`
	City     string `form:"city" validate:"required" chn:"市/区"`
	County   string `form:"county"`
	Address  string
}

func (form *AddressFrom) Valid() error {
	var address string
	regionRepository := repository.UserRepository{}
	if province, exist := regionRepository.FindOneById(form.Province); exist {
		address += province.Name
	} else {
		return errors.New("省份信息设置失败")
	}

	if city, exist := regionRepository.FindOneByIdAndParentId(form.City, form.Province); exist {
		address += city.Name
	} else {
		return errors.New("市信息设置失败")
	}

	if county, exist := regionRepository.FindOneByIdAndParentId(form.County, form.City); exist {
		address += county.Name
	}
	form.Address = address
	return nil
}

type EditPasswordForm struct {
	OldPwd     string `form:"old" validate:"required,password" chn:"旧密码"`
	NewPwd     string `form:"new" validate:"required,password" chn:"新密码"`
}

func (form *EditPasswordForm) Update(user entity.User) error {
	if user.Password != user.GetPassword(form.OldPwd) {
		return errors.New("旧密码错误！")
	}

	db := util.GetMysqlPool().Handler()
	db.Model(&user).Update("password", user.GetPassword(form.NewPwd))
	return nil
}

type UserForm struct {
	Nickname string `form:"nickname" validate:"required,min=2,max=32" chn:"昵称"`
	Username string `form:"username" validate:"required,min=2,max=32" chn:"用户名"`
	Sex      int    `form:"sex"`
	Province string `form:"province" validate:"required"`
	City     string `form:"city" validate:"required"`
	County   string `form:"county"`
	Address  string
	Company  string `form:"company" validate:"required,max=128"`
	Job      string `form:"job" validate:"required,max=128"`
	JobRank  string `form:"job_rank" validate:"required,max=128"`
}

func (form *UserForm) Valid() error {
	var address string
	regionRepository := repository.UserRepository{}
	if province, exist := regionRepository.FindOneById(form.Province); exist {
		address += province.Name
	} else {
		return errors.New("省份信息设置失败")
	}

	if city, exist := regionRepository.FindOneByIdAndParentId(form.City, form.Province); exist {
		address += city.Name
	} else {
		return errors.New("市信息设置失败")
	}

	if county, exist := regionRepository.FindOneByIdAndParentId(form.County, form.City); exist {
		address += county.Name
	}
	form.Address = address
	return nil
}

type RegisterForm struct {
	Phone    string `form:"phone" validate:"phone,required" chn:"手机号"`
	Password string `form:"password" validate:"required,password" chn:"密码"`
	Code     string `form:"code" validate:"len=6,required" chn:"手机验证码"`
}

type ResetPasswordForm struct {
	Phone    string `form:"phone" validate:"phone,required" chn:"手机号"`
	Password string `form:"password" validate:"required,password" chn:"密码"`
	Code     string `form:"code" validate:"len=6,required" chn:"手机验证码"`
}

type LoginForm struct {
	Phone    string `form:"phone" validate:"phone,required" chn:"手机号"`
	Password string `form:"password" validate:"required" chn:"密码"`
}

func (form *LoginForm) Login() (entity.User, error) {
	var user entity.User
	db := util.GetMysqlPool().Handler()
	// fmt.Println(form.Password)
	if db.Where("phone = ?", form.Phone).
		First(&user).RecordNotFound() {
		return user, errors.New("手机号未注册")
	}

	if db.Where("phone = ? and password = ?", form.Phone, user.GetPassword(form.Password)).
		First(&user).RecordNotFound() {
		return user, errors.New("手机号或密码错误")
	}
	user.RefreshLoginTime()
	db.Model(&user).Update("last_login_time", user.LastLoginTime)
	return user, nil
}

func (form *RegisterForm) Valid() error {
	smsService := service.SmsService{}
	return smsService.VerifyCode(form.Phone, entity.SmsCodeRegister, form.Code)
}

func (form *RegisterForm) Register() (entity.User, bool) {
	db := util.GetMysqlPool().Handler()
	user := entity.User{Phone: form.Phone, CreatedAt: time.Now().Unix(), Sex: util.AllOfGender}
	user.Status = util.UserStatusReady
	// password := util.GetSystemValue("default_password")
	user.SetPassword(form.Password)
	user.SetToken()
	user.Avatar = "avatar/user/default.jpg"
	user.Nickname = "会员_" + user.Phone[len(user.Phone)-4:]
	if db.Create(&user).RowsAffected > 0 {
		return user, true
	}
	return user, false
}

func (form *ResetPasswordForm) Valid() error {
	smsService := service.SmsService{}
	return smsService.VerifyCode(form.Phone, entity.SmsCodeResetPassword, form.Code)
}

func (form *ResetPasswordForm) ResetPassword() (entity.User, error) {
	var user entity.User
	db := util.GetMysqlPool().Handler()
	if db.Where("phone = ?", form.Phone).First(&user).RecordNotFound() {
		return user, errors.New("账号不存在")
	}
	user.SetPassword(form.Password)
	user.SetToken()
	if db.Save(&user).RowsAffected <= 0 {
		return user, errors.New("重置失败")
	}
	return user, nil
}

func (form *UserForm) UploadAvatar(c *gin.Context, user entity.User) (string, error) {
	folder := util.CreateDir("storage/avatar/user")
	file, _ := c.FormFile("file")
	if file.Size > 1024*1024 {
		return "", errors.New("上传头像不能大于1M")
	}
	ext, _ := util.GetImgExt(file)
	// ext := path.Ext(file.Filename)
	filename := filepath.Join(folder, strconv.Itoa(int(user.Id))+ext)
	if err := c.SaveUploadedFile(file, filename); err == nil {
		timeUnix := time.Now().Unix()
		return filepath.ToSlash(filename[8:]) + "?" + strconv.FormatInt(timeUnix, 10), nil
	}
	return "", errors.New("头像保存失败!")
}

func (form *UserForm) SetProfile(user *entity.User) error {
	db := util.GetMysqlPool().Handler()
	if db.Model(user).Updates(form).RowsAffected > 0 {
		return nil
	}

	return errors.New("更新失败")
}
